﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Engine.Sgml.Validation.Rules;
using Engine.Sgml.Matching;
using System.Diagnostics;

namespace Engine.Sgml.Validation {
    internal sealed class EndElementValidator : IElementValidator {
        private ValidationRuleCollection rules;

        public EndElementValidator(ValidationRuleCollection rules) {
            Guard.ArgumentNotNull(rules, "rules");
            this.rules = rules;
            }

        /// <summary>
        /// Validates that the closing node correspond to the specified element.
        /// </summary>
        /// <param name="node">A closable element.</param>
        /// <param name="element">An end element.</param>
        /// <returns>An ancestor of the specified element.</returns>
        public SElement Validate(SElement element, SElement node) {
            Debug.Assert(node.HasElements && node.LastNode.NodeType == SgmlNodeType.EndElement && node.LastNode == element);
            node.Nodes.Pop();
            if (rules[element].Ignore(element, node))
                return node;
            SElement closed = node;
            while (rules[closed].CanClose(closed, element)) {
                if (closed.Parent == null)
                    return closed;
                else if (ElementMatcher.Match(closed, element))
                    return closed.Parent;
                else
                    closed = closed.Parent;
                }
            return node;
            }
        }
    }
